package com.shell.governor.user.controller;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.shell.bee.base.annotation.Logging;
import com.shell.bee.base.utils.SpringContextUtil;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.base.utils.SystemUtil;
import com.shell.bee.entity.auth.AuthOrgan;
import com.shell.bee.entity.auth.AuthUser;
import com.shell.bee.entity.mvc.RetMsg;
import com.shell.bee.file.po.PubFile;
import com.shell.bee.file.service.PubFileService;
import com.shell.bee.file.service.PubFileUploadService;
import com.shell.bee.mvc.controller.BaseController;
import com.shell.bee.persistence.model.PageLimit;
import com.shell.framework.utils.CommonDataUtil;
import com.shell.framework.utils.CommonFileUtil;
import com.shell.governor.authorization.po.PubRole;
import com.shell.governor.authorization.service.PubRoleService;
import com.shell.governor.organization.po.PubOrgan;
import com.shell.governor.organization.service.PubOrganService;
import com.shell.governor.user.UserEvent;
import com.shell.governor.user.dao.PubUserOrganDao;
import com.shell.governor.user.po.PubUser;
import com.shell.governor.user.po.PubUserExtra;
import com.shell.governor.user.po.PubUserOpt;
import com.shell.governor.user.rx.PostUserToEsignSubscriber;
import com.shell.governor.user.service.PubUserExtraService;
import com.shell.governor.user.service.PubUserOptService;
import com.shell.governor.user.service.PubUserService;
import com.shell.governor.user.vo.PubUserVo;
import com.shell.governor.user.vo.UserQueryVo;
import com.shell.governor.util.ExcelGenUtil;

import rx.Observable;

@RestController
public class PubUserController extends BaseController {
	@Autowired
	private PubUserService userService;
	@Autowired
	private PubUserExtraService userExtraService;
	@Autowired
	private PubRoleService roleService;
	@Autowired
	private PubOrganService organService;
	@Autowired
	private PubUserOptService userOptService;
	@Resource(name = "${file.updownload.service}")
	private PubFileUploadService pubFileUploadService;
	@Autowired
	private PubFileService pubFileService;
	@Autowired
	private PostUserToEsignSubscriber postUserToEsignSubscriber;

	@RequestMapping
	@Logging(module = "��������", methods = "��������")
	public RetMsg addUser(PubUserVo pubUserVo, HttpServletRequest request) throws Exception {
		if (!this.userService.checkCodeUnique(pubUserVo)) {
			return new RetMsg("error", "��������������");
		}
		int value = this.userService.saveUser(pubUserVo);
		if (value == 1) {
			return new RetMsg("success", "��������");
		}
		return new RetMsg("error", "��������");
	}

	@RequestMapping
	@Logging(module = "��������", methods = "��������")
	public RetMsg updateUser(PubUserVo pubUserVo, HttpServletRequest request) throws Exception {
		if (!this.userService.checkCodeUnique(pubUserVo)) {
			return new RetMsg("error", "��������������");
		}
		int value = this.userService.updateUser(pubUserVo);
		if (value == 1) {
			return new RetMsg("success", "��������");
		}
		return new RetMsg("error", "��������");
	}

	@RequestMapping
	@Logging(module = "��������", methods = "����������")
	public RetMsg updateLoginName(PubUserVo pubUserVo, HttpServletRequest request) throws Exception {
		pubUserVo.setUserId(CommonDataUtil.getUserId());
		if (!this.userService.checkCodeUnique(pubUserVo)) {
			return new RetMsg("error", "��������������");
		}
		int value = this.userService.updateLoginName(pubUserVo);
		if (value == 1) {
			return new RetMsg("success", "��������");
		}
		return new RetMsg("error", "��������");
	}

	@RequestMapping
	@Logging(module = "��������", methods = "��������")
	public RetMsg deleteUser(PubUser user, String entId, HttpServletRequest request) throws Exception {
		return this.userService.deleteUser(user, entId);
	}

	@RequestMapping
	@Logging(module = "��������", methods = "������������")
	public RetMsg updateState(String userState, String userId, String entId, HttpServletRequest request)
			throws Exception {
		int value = this.userService.updateState(userState, userId, entId);
		if (value > 0) {
			return new RetMsg("success", "������������!");
		}
		return new RetMsg("error", "��������������");
	}

	@RequestMapping
	@Logging(module = "������������", methods = "��������")
	public List<PubUserVo> selectUsersByPage(PageLimit limit, PubUserVo user, HttpServletRequest request)
			throws Exception {
		if (!StringUtil.emptyAndNull(user.getOrganId())) {
			user.setStruPath(StringUtil.getParameterLike(user.getOrganId()));
			user.setOrganId(null);
		}
		return this.userService.selectUsersByPage(limit, user);
	}

	@RequestMapping
	@Logging(module = "������������", methods = "��������")
	public List<PubUserVo> organUserMgt(PageLimit limit, PubUserVo user, HttpServletRequest request) throws Exception {
		AuthUser curUser = CommonDataUtil.getCurUser();
		AuthOrgan ent = CommonDataUtil.getCurEnt();
		if (StringUtil.emptyAndNull(user.getOrganId())) {
			user.setEntId(ent.getOrganId());
		}
		if (!StringUtil.emptyAndNull(user.getOrganId())) {
			user.setStruPath(StringUtil.getParameterLike(user.getOrganId()));
			user.setOrganId(null);
		}
		return this.userService.selectUsersByPage(limit, user);
	}

	@RequestMapping
	@ResponseBody
	@Logging(module = "��������", methods = "��������")
	public RetMsg resetUserPassword(String userId) throws Exception {
		return this.userService.resetUserPassword(userId);
	}

	@RequestMapping
	@Logging(module = "��������", methods = "������������������")
	public RetMsg sendVerificationCode(String phoneNo, String userName, HttpServletRequest request) throws Exception {
		String verifyCode = this.userService.sendVerificationCode(phoneNo, userName);
		HttpSession session = request.getSession();
		session.setAttribute("verifyCode", verifyCode);
		session.setMaxInactiveInterval(120);
		return new RetMsg("success", "������������");
	}

	@RequestMapping
	@Logging(module = "��������", methods = "��������")
	public RetMsg changePhone(String code, PubUser user, HttpServletRequest request) throws Exception {
		HttpSession session = request.getSession(true);
		if ((String) session.getAttribute("verifyCode") == null) {
			return new RetMsg("error", "������������ ����������������");
		}
		String verifyCode = (String) session.getAttribute("verifyCode");
		return this.userService.changePhone(user, verifyCode, code);
	}

	@RequestMapping
	@Logging(module = "��������", methods = "��������")
	public RetMsg modifyUserPassword(String newPassword, String oldPassword) throws Exception {
		int value = this.userService.modifyUserPassword(CommonDataUtil.getUserId(), newPassword, oldPassword);
		if (value > 0) {
			return new RetMsg("success", "��������������");
		}
		return new RetMsg("error", "��������������������������������");
	}

	@RequestMapping
	@Logging(module = "��������", methods = "������������������")
	public RetMsg checkCode(PubUserVo user) throws Exception {
		return initRetMsg("success", false, Boolean.valueOf(this.userService.checkCodeUnique(user)));
	}

	@RequestMapping
	@Logging(module = "��������", methods = "����������������")
	public void selectUsersExport(PageLimit limit, PubUserVo user, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		if (!StringUtil.emptyAndNull(user.getOrganId())) {
			user.setStruPath(StringUtil.getParameterLike(user.getOrganId()));
			user.setOrganId(null);
		}
		List<PubUserVo> users = this.userService.selectUsersByPage(limit, user);
		Map<String, Object> map = new HashMap();
		map.put("datas", users);
		InputStream is = ExcelGenUtil.getInstance().GenerateExcelForStream("/template/excel/userMgtList.xlsx", map);
		CommonFileUtil.writeFileToClient("��������.xlsx", is, response, request);
	}

	@RequestMapping
	@Logging(module = "��������", methods = "����ID��������")
	public PubUserVo selectUserById(String userId) throws Exception {
		return this.userService.selectUser(userId);
	}

	@RequestMapping
	@Logging(module = "��������", methods = "������������������")
	public RetMsg checkPhoneNoUnique(String userId, String phoneNo) throws Exception {
		return initRetMsg("success", false,
				Boolean.valueOf(this.userService.checkPhoneNoUnique(userId, null, phoneNo)));
	}

	@RequestMapping
	@Logging(module = "������������", methods = "������������������")
	public String getUserPhone() throws Exception {
		PubUserVo userVo = this.userService.selectUser(CommonDataUtil.getCurUser().getUserId());
		if (userVo != null) {
			return userVo.getPhoneNo();
		}
		return "";
	}

	@RequestMapping
	@Logging(module = "��������", methods = "������������������������������")
	public List<PubUserVo> selectEntUsersByPage(PageLimit limit, PubUserVo user, HttpServletRequest request)
			throws Exception {
		if (!StringUtil.emptyAndNull(user.getOrganId())) {
			user.setStruPath(StringUtil.getParameterLike(user.getOrganId()));
			user.setOrganId(null);
		}
		return this.userService.selectEntUsersByPage(limit, user);
	}

	@RequestMapping
	@Logging(module = "��������", methods = "����������������")
	public void selectEntUsersExport(PageLimit limit, PubUserVo user, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		if (!StringUtil.emptyAndNull(user.getOrganId())) {
			user.setStruPath(StringUtil.getParameterLike(user.getOrganId()));
			user.setOrganId(null);
		}
		List<PubUserVo> users = this.userService.selectEntUsersByPage(limit, user);
		Map<String, Object> map = new HashMap();
		map.put("datas", users);
		InputStream is = ExcelGenUtil.getInstance().GenerateExcelForStream("/template/excel/userMgtList.xlsx", map);
		CommonFileUtil.writeFileToClient("��������.xlsx", is, response, request);
	}

	@RequestMapping
	@Logging(module = "��������", methods = "������������")
	public RetMsg addUserForEnt(PubUserVo userVo) {
		Boolean isNeedApprover = Boolean.valueOf(this.userService.addUserForEnt(userVo));
		if (isNeedApprover.booleanValue()) {
			return initRetMsg("success", "����������������������1-3����������������������������������������");
		}
		return initRetMsg("success", "��������");
	}

	@RequestMapping
	@Logging(module = "��������", methods = "������������")
	public RetMsg updateUserForEnt(PubUserVo userVo) {
		this.userService.updateUserForEnt(userVo);
		return initRetMsg("success", "��������");
	}

	@RequestMapping
	@Logging(module = "��������", methods = "��������")
	List<PubUserVo> selectUserForFirstTrial(PageLimit limit, UserQueryVo userVo) {
		String[] notStates = { "D", "U", "E", "I" };
		userVo.setNotStates(notStates);
		if (StringUtil.notEmpty(userVo.getQueryValue())) {
			userVo.setQueryValue(StringUtil.getParameterLike(userVo.getQueryValue()));
		}
		return this.userService.selectUserForApr(limit, userVo);
	}

	@RequestMapping
	@Logging(module = "��������", methods = "��������")
	List<PubUserVo> selectUserForLastTrial(PageLimit limit, UserQueryVo userVo) {
		String[] notStates = { "D", "U", "E", "I", "0", "2" };
		userVo.setNotStates(notStates);
		if (StringUtil.notEmpty(userVo.getQueryValue())) {
			userVo.setQueryValue(StringUtil.getParameterLike(userVo.getQueryValue()));
		}
		return this.userService.selectUserForApr(limit, userVo);
	}

	@RequestMapping
	@Logging(module = "��������", methods = "��������")
	public RetMsg firstTrialPass(PubUserOpt userOpt) {
		this.userService.firstTrialPass(userOpt);
		return initRetMsg("success", "������������");
	}

	@RequestMapping
	@Logging(module = "��������", methods = "��������")
	public RetMsg firstTrialReject(PubUserOpt userOpt) {
		this.userService.firstTrialReject(userOpt);
		return initRetMsg("success", "������������");
	}

	@RequestMapping
	@Logging(module = "��������", methods = "��������")
	public RetMsg lastTrialPass(PubUserOpt userOpt) {
		this.userService.lastTrialPass(userOpt);
		return initRetMsg("success", "������������");
	}

	@RequestMapping
	@Logging(module = "��������", methods = "��������")
	public RetMsg lastTrialReject(PubUserOpt userOpt) {
		this.userService.lastTrialReject(userOpt);
		return initRetMsg("success", "������������");
	}

	@RequestMapping
	@Logging(module = "��������", methods = "����������������")
	public PubUserOpt getLastOpt(String userId, String entId) {
		return this.userOptService.getLastOpt(userId, entId);
	}

	@RequestMapping
	@Logging(module = "��������", methods = "������������")
	public Map<String, Object> getEntUserInfo(String userId, String entId) {
		PubUser user = (PubUser) this.userService.selectByKey(userId);
		PubUserExtra userExtra = new PubUserExtra();
		userExtra.setUserId(userId);
		userExtra.setEntId(entId);
		userExtra = (PubUserExtra) this.userExtraService.selectOne(userExtra);

		List<PubRole> roles = this.roleService.selectUserRole(userId, entId);

		PubOrgan organ = (PubOrgan) this.organService.selectByKey(entId);

		Map<String, Object> m = new HashMap();
		m.put("user", user);
		m.put("userExtra", userExtra);
		m.put("roles", roles);
		m.put("entName", organ.getOrganName());
		return m;
	}

	@RequestMapping
	@Logging(module = "��������", methods = "����������������")
	public RetMsg checkPhoneNoForExit(String phoneNo, String entId) {
		UserQueryVo userVo = new UserQueryVo();
		userVo.setPhoneNo(phoneNo);
		userVo.setUserState("E");
		List<PubUserVo> users = this.userService.queryUser(userVo);

		PubUserVo curUser = null;
		if ((users == null) || (users.size() == 0)) {
			return initRetMsg("error", false, "������������");
		}
		for (PubUserVo user : users) {
			if (entId.equals(user.getEntId())) {
				curUser = user;
			}
		}
		return new RetMsg("success", false, "", curUser != null ? curUser : users.get(0));
	}

	@RequestMapping
	@Logging(module = "��������", methods = "��������/������������")
	public RetMsg uploadUserInfo(PubUser user, String msgVerifyCode) throws Exception {
		if (!StringUtil.emptyAndNull(user.getUserId())) {
			int u = this.userService.uploadUserInfo(user, msgVerifyCode);
			if (u == 1) {
				if ("on".equals(SpringContextUtil.getProperty("esign.switch"))) {
					UserEvent event = new UserEvent();
					event.setUser(user);
					Observable<UserEvent> observers = Observable.just(event);
					observers.subscribe(this.postUserToEsignSubscriber);
				}
				return new RetMsg("success", "����������");
			}
			if (u == 2) {
				return new RetMsg("error", "����������������");
			}
			if (u == 3) {
				return new RetMsg("error", "����������������");
			}
			if (u == 4) {
				return new RetMsg("error", "����������������");
			}
		}
		return new RetMsg("error", "����������");
	}

	@RequestMapping
	@Logging(module = "��������", methods = "������������")
	public RetMsg sendSms(@RequestParam(name = "phoneNo") String phoneNo) throws Exception {
		String smsCode = this.userService.sendSMS(phoneNo);
		boolean show = false;
		if (!SystemUtil.SystemMode.prod.equals(SystemUtil.getSystemMode())) {
			show = true;
		}
		return new RetMsg("success", show, "����������������,��������" + smsCode);
	}

	@RequestMapping
	@Logging(module = "��������", methods = "��������")
	public RetMsg setDefault(String userId, String entId) {
		this.userService.setDefault(userId, entId);
		return new RetMsg("success", false, "��������������");
	}

	@RequestMapping
	@Logging(module = "��������", methods = "������������")
	public RetMsg uploadUserPhoto(@RequestParam(value = "file", required = false) MultipartFile file, String fileType,
			String savePath, String fileName) throws Exception {
		this.pubFileService.clearRelateId(CommonDataUtil.getUserId(), fileType);
		RetMsg r = this.pubFileUploadService.saveFile(file, fileType, savePath, fileName);
		PubFile pubFile = (PubFile) r.getBean();
		this.pubFileService.setRelateId(pubFile.getFileId(), CommonDataUtil.getUserId(), fileType);
		return r;
	}

	@RequestMapping({ "/auth/getUserPhotoByPhone" })
	@Logging(module = "��������", methods = "������������������")
	public PubFile getUserPhotoByPhone(String userPhone, String fileType) {
		if (StringUtil.emptyAndNull(userPhone)) {
			return null;
		}
		PubUser user = this.userService.selectUserByPhone(userPhone);
		if (user != null) {
			PubFile pf = new PubFile();
			pf.setRelateId(user.getUserId());
			pf.setFileType(fileType);
			List<PubFile> list = this.pubFileService.selectFiles(pf);
			if ((list != null) && (list.size() > 0)) {
				return (PubFile) list.get(0);
			}
		}
		return null;
	}

	@RequestMapping
	@Logging(module = "��������", methods = "����������������������")
	public PubUser selectUserByIdCard(String certNo) {
		return this.userService.selectUserByIdCard(certNo);
	}

	@RequestMapping
	@Logging(module = "��������", methods = "��������������")
	public RetMsg modifyMobileUserPassword(String newPassword, String oldPassword) throws Exception {
		int value = this.userService.modifyUserPassword(CommonDataUtil.getUserId(), newPassword, oldPassword);
		if (value > 0) {
			return new RetMsg("success", "��������������");
		}
		return new RetMsg("error", "��������������");
	}
}
